package uiLayer.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import utilLayer.Validator;
import modelLayer.Block;
import modelLayer.Schedule;
import modelLayer.TeachingBlock;

/**
 * ConflictCheckSupporter registers teaching block objects which the user selects
 * in order to move them to the schedule, and the block objects which the user selects
 * as target places in the schedule. This class is responsible to call conflict check 
 * on the Validator class.
 *
 */
public class ConflictCheckSupporter {
	private int col;
	private int row;
	private int sourceIndex;
	private TeachingBlock sourceObject;
	private Block targetObject;
	private Validator v;
	private Schedule sch;
	private List<Boolean> suggestions;
	
	
	/**
	 * Initiates a Validator instance. Takes a schedule object as parameter.
	 * @param schedule
	 */
	public ConflictCheckSupporter(Schedule schedule) {
		v = new Validator();
		sch = schedule;
		resetSuggestions();
	}
	
	/**
	 * Calls the checkConflict() method on the Validator sending the targetObject (a block)
	 * and the sourceObject (a teaching block) as parameters.
	 * Shows the available places of the schedule if there occurs a conflict.
	 * 
	 * @return false if no conflict occurs, true if conflict occurs
	 */
	public boolean checkConflict(){
		
		boolean res = v.checkConflict(targetObject.getBlockNumber(), sourceObject);
		if (res){
			refreshSuggestions();
		}
		return res;
	}
	
	/**
	 * Refreshes the suggestion list responding to the state found in the
	 * database by calling a helper method.
	 */
	private void refreshSuggestions(){
		try {
			suggestions = convert(this.showSuggestions());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Helper method to convert the list of integers which is provided by the Validator 
	 * into a list of booleans responding to the index values of the tableModel behind
	 * the scheduleTable.
	 * 
	 * @param blockNumbers
	 * @return
	 */
	private List<Boolean> convert(List<Integer> blockNumbers) {
		int numberOfBlocksPerDay = 7;
		List<Boolean> res = new ArrayList<>(numberOfBlocksPerDay * 5);
		for (int i = 0; i < numberOfBlocksPerDay * 5; i++){
			if  (blockNumbers.contains(i+1)){
				res.add(true);
			}
			else {
				res.add(false);
			}
		}
		return res;
	}
	
	/**
	 * Method to execute a call to the Validator in order to get a list of available places.
	 * 
	 * @return a list of Integers
	 * @throws Exception
	 */
	private List<Integer> showSuggestions() throws Exception {
		return v.showSuggestions(sch, targetObject.getBlockNumber(), sourceObject);
	}
	
	/**
	 * A method used by the TableCellRenderer of the scheduleTable in order to display
	 * the conflicting cells in a different color. Takes the coordinates of a cell in
	 * the scheduleTable as parameters (a column and a row value). The method calculates
	 * which index value of the suggestions list responds to the coordinates in the table.
	 * 
	 * @param column
	 * @param row
	 * @return a boolean value
	 */
	public boolean isBlockAvailable(int column, int row) {
		int numberOfBlocksPerDay = 7;
		int indexPosition = column * numberOfBlocksPerDay + row;  
		return this.suggestions.get(indexPosition);
	}
	
	/**
	 * Resets the suggestion list by creating a list of booleans only containing true values.
	 */
	private void resetSuggestions(){
		suggestions = new ArrayList<Boolean>(Collections.nCopies(35, true));
	}
	
	
	/**
	 * Sets the sourceObject taking a teaching block and an index value as parameters.
	 * 
	 * @param selectedValue
	 * @param sourceIndex
	 */
	public void setSource(TeachingBlock selectedValue, int sourceIndex) {
		
		this.setSourceObject(selectedValue);
		this.setSourceIndex(sourceIndex);
		resetSuggestions();
	}
	
	/**
	 * Sets the target object taking a block object, a row value and a column value as parameters.
	 * @param row
	 * @param col
	 * @param targetBlock
	 */
	public void setTarget(int row, int col, Block targetBlock) {
		
		this.setTargetObject(targetBlock);
		this.setTargetCol(col);
		this.setTargetRow(row);
	}



	/**
	 * @return the targetX
	 */
	public int getTargetCol() {
		return col;
	}

	/**
	 * @param col the targetX to set
	 */
	public void setTargetCol(int col) {
		this.col = col;
	}

	/**
	 * @return the targetY
	 */
	public int getTargetRow() {
		return row;
	}

	/**
	 * @param row the targetY to set
	 */
	public void setTargetRow(int row) {
		this.row = row;
	}

	/**
	 * @return the sourceIndex
	 */
	public int getSourceIndex() {
		return sourceIndex;
	}

	/**
	 * @param sourceIndex the sourceIndex to set
	 */
	private void setSourceIndex(int sourceIndex) {
		this.sourceIndex = sourceIndex;
	}

	/**
	 * @return the selectedObject
	 */
	public TeachingBlock getSourceObject() {
		return sourceObject;
	}

	/**
	 * @param selectedObject the selectedObject to set
	 */
	private void setSourceObject(TeachingBlock selectedObject) {
		this.sourceObject = selectedObject;
	}

	/**
	 * @return the targetOgject
	 */
	public Block getTargetObject() {
		return targetObject;
	}

	/**
	 * @param targetOgject the targetObject to set
	 */
	public void setTargetObject(Block targetOgject) {
		this.targetObject = targetOgject;
	}

	
}
